package com.gaohc.framework.config.satoken;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.strategy.SaStrategy;
import com.gaohc.common.config.SystemConfig;
import com.gaohc.common.constant.Constants;
import com.gaohc.common.core.domain.AjaxJson;
import com.gaohc.framework.config.encrypt.GbxDispatcherServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


/**
 * [Sa-Token 权限认证] 配置类 
 * @author kong
 *
 */
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
	
	/**
	 * 注册Sa-Token 的拦截器，打开注解式鉴权功能 
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 注册Sa-Token的路由拦截器
		registry.addInterceptor(new SaAnnotationInterceptor())
				.addPathPatterns("/**");

	}

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry)
	{
		/** 本地文件上传路径 */
		registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
				.addResourceLocations("file:" + SystemConfig.getProfile() + "/");

	}

	/**
	 * 注册 [Sa-Token全局过滤器]
	 */
	@Bean
	public SaServletFilter getSaServletFilter() {
		return new SaServletFilter()
			// 拦截与排除 path
			.addInclude("/**").addExclude("/favicon.ico")
			// 全局认证函数
			.setAuth(obj -> {
				// ...
			})
			// 异常处理函数
			.setError(e -> AjaxJson.getError(e.getMessage()))
			// 前置函数：在每次认证函数之前执行
			.setBeforeAuth(obj -> {
				// ---------- 设置跨域响应头 ----------
				SaHolder.getResponse()
						// 允许指定域访问跨域资源
						.setHeader("Access-Control-Allow-Origin", "*")
						// 允许所有请求方式
						.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
						// 有效时间
						.setHeader("Access-Control-Max-Age", "3600")
						// 允许的header参数
						.setHeader("Access-Control-Allow-Headers", "*");
				// 如果是预检请求，则立即返回到前端
				SaRouter.match(SaHttpMethod.OPTIONS)
						.free(r -> System.out.println("--------OPTIONS预检请求，不做处理"))
						.back();
			})
			;
	}

    /**
     * 重写 Sa-Token 框架内部算法策略 
     */
    @Autowired
    public void rewriteSaStrategy() {
    	// 重写Sa-Token的注解处理器，增加注解合并功能 
    	SaStrategy.me.getAnnotation = AnnotatedElementUtils::getMergedAnnotation;
    }

	/**
	 * 使用自定义的请求转发
	 *
	 * @return
	 */
	@Bean
	@Qualifier(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
	public DispatcherServlet dispatcherServlet() {
		return new GbxDispatcherServlet();
	}

}
